﻿<#
    Script    :RemoteStsAdm
    Author    :Riwut Libinuko
    Blog      :http://blog.libinuko.com
    Copyright :© IdeasFree - cakriwut@gmail.com, 2011. All rights reserved.
#>

<#

#>

function InvokeScheduleTasks
{
<#
.SYNOPSIS
Create , Execute and Return command execution result using schedule tasks. 
		
.DESCRIPTION
The function takes command line input to be executed by schedule tasks.
    
.INPUTS
None. You can not pipe objects to InvokeScheduleTasks
	
.OUTPUTS
System.String. Return result object of the Schedule Task status
		
.PARAMETER CommandLine
MANDATORY parameter to specify the command line. This is CMD shell command. You must enclose space in the double quotes. 
	
.PARAMETER UserName
MANDATORY parameter username. This user must have logon-as-service rights on the target machine. He/She must also have access to other sub-system.
        
.PARAMETER Password
MANDATOR parameter password. 

.PARAMETER Taskname
OPTIONAL parameter to identify the taskname. DEFAULT "PSTask dd-MM-yyyy hhmmss"
			

.EXAMPLE
	PS>  InvokeScheduleTasks -commandline "dir c:\" -username contoso\foe  -password doe 
			

	Description
	-----------
	Execute "dir c:\" in the target machine.
		
.EXAMPLE
	PS> InvokeScheduleTasks -commandline "`"%programfiles%\common files\microsoft shared\web server extensions\12\bin\stsadm.exe`"" -username contoso\foe  -password doe 


	Description
	-----------
	Execute fullpath of commandline. Don't forget to put the commandline inside double quote.
            
.LINK
    Author blog  : IdeasForFree  (http://blog.libinuko.com)
.LINK
    Author email : cakriwut@gmail.com
#>
   param(             
       [Parameter(Mandatory=$true,Position=0)]
       [System.String]            
       $commandline ,
       
       [Parameter(Mandatory=$true,Position=1)]  
       [String] 
       $username,
       
       [Parameter(Mandatory=$true,Position=2)]
       [String] 
       $password   ,
       
       [System.String]
       $taskname = (get-date -format "'PSTask' dd-MM-yyyy hhmmss")
 
   )   
    
    $logFile = "{0}.log" -f [System.Guid]::NewGuid().ToString()
    schtasks /create /tn $taskname /tr ("cmd /c {0} > %systemroot%\temp\{1} 2>&1" -f ($commandline -replace "`"","`\`""),$logFile) /sc weekly  /ru $username /rp $password | out-null

    schtasks /run /tn $taskname /I | out-null

    write-host "Waiting task execution." -nonewline -foreground green
    do {
      $taskStatus = schtasks /query /fo csv /v | convertfrom-csv | ? { $_.TaskName.TrimStart("\") -eq "$taskname"}
      sleep 10
      write-host "." -nonewline -foreground green

    } while ($taskStatus."Status" -eq "Running")

    write-host "Completed!" -foreground green

    schtasks /delete /tn $taskname /f | out-null
    if(test-path "$env:systemroot\temp\$logFile")
    {
       get-content "$env:systemroot\temp\$logFile"
       sleep 10
       remove-item "$env:systemroot\temp\$logFile" -force
    } 
        
    return $taskStatus
}

function Invoke-RemoteStsAdm
{
<#
.SYNOPSIS
	Run stsadm command on the remote machine. 
		
.DESCRIPTION
This is an enhancement of stsadm, that enable you to execute stsadm on the remote machine. 
    
All the options are explained in the parameter section.
    
.INPUTS
None. You can not pipe objects to Invoke-RemoteStsAdm
	
.OUTPUTS
System.String. Return execution status and stsadm output result (if any).
		
.PARAMETER Options
MANDATORY parameter to specify stsadm command parameter. For example "-o enumsites -url http://ideasfree.com"

.PARAMETER ComputerName
MANDATORY parameter to specify the target ComputerName. Default: local computer. 
	
.PARAMETER Credential
MANDATORY parameter of PSCredential to connect to the remote machine.
        
.PARAMETER CmdCredential
OPTIONAL parameter of PSCredential to execute stsadm. Default: same as Credential If not null, CommandLine will be executed using this credential. 
		
.PARAMETER Version
OPTIONAL parameter to specify SharePoint version. Available options: 12, 14. Default: 12. 

.EXAMPLE   
	PS> Invoke-RemoteStsAdm "-o enumsites -url http://ideasfree.com" -ComputerName "targetComputer" -Credential (Get-Credential)
			

	Description
	-----------
	Execute "stsadm -o enumsites -url http://ideasfree.com" in the targetComputer using prompted credential. 

.EXAMPLE  
    PS> $credExec = Get-Credential 
	PS> Invoke-RemoteStsAdm "-o enumsites -url http://ideasfree.com" -ComputerName "targetComputer" -Credential (Get-Credential) -CmdCredential $credExec
			

	Description
	-----------
	Connect to targetComputer using prompted credential. Execute "stsadm -o enumsites -url http://ideasfree.com" using from $credExec variable.    
		
.EXAMPLE
	PS> Invoke-RemoteStsAdm "-o enumsites -url http://ideasfree.com" -ComputerName "targetComputer" -Credential (Get-Credential) -Version 14
			

	Description
	-----------
	Execute "stsadm -o enumsites -url http://ideasfree.com" in the targetComputer using prompted credential. Where targetComputer is running SharePoint 2010.
    
            
.LINK
    Author blog  : IdeasForFree  (http://blog.libinuko.com)
.LINK
    Author email : cakriwut@gmail.com
#>
   param(
       [Parameter(Mandatory=$true, Position=0)]
       [System.String]            
       $option ,
       
       [Parameter(Mandatory=$true,Position=1)]
       [System.Management.Automation.PSCredential]        
       $Credential  ,
         
       [String] 
       $ComputerName = "."    ,
       
       [System.Management.Automation.PSCredential]        
       $CmdCredential     ,       
      
       [System.String]
       [ValidateSet('12','14')]
       $version="12"
   )
   
   $commandLine = "`"%programfiles%\common files\microsoft shared\web server extensions\{0}\bin\stsadm.exe`" {1}" -f $version,$option
   return Invoke-RemoteCommand $commandLine -Credential $Credential -ComputerName $computerName -CmdCredential $CmdCredential

}

function Invoke-RemoteCommand 
{
<#
.SYNOPSIS
	Run commands on local and remote computers without double-hop issue. 
		
.DESCRIPTION
The function takes command line input (NOT a PowerShell scriptblock) and execute on target machine, given that:
   - Target machine has Enable-PSRemoting and WinRM is running
   - The user has access to target machine
        
If you want to execute PowerShell scriptblock, the scriptblock must be commandline argument of the ps.exe.
    
All the options are explained in the parameter section.
    
.INPUTS
None. You can not pipe objects to Invoke-RemoteCommand
	
.OUTPUTS
System.String. Return result object of the RemoteCommand execution status
		
.PARAMETER CommandLine
MANDATORY parameter to specify the command line. This is CMD shell command. You must enclose space in the double quotes. 

.PARAMETER ComputerName
MANDATORY parameter to specify the target ComputerName. Default: local computer. 
	
.PARAMETER Credential
MANDATORY parameter of PSCredential that has access to run Invoke-Command to the remote machine.
        
.PARAMETER CmdCredential
OPTIONAL parameter of PSCredential that has access to execute the command. If not null, CommandLine will be executed using this credential. 
		

.EXAMPLE   
	PS> Invoke-RemoteCommand -commandline "dir c:\" -ComputerName "targetComputer" -Credential (Get-Credential)
			

	Description
	-----------
	Execute "dir c:\" in the targetComputer using prompted credential. The "dir c:\" will be executed using prompted credential.

.EXAMPLE  
    PS> $credExec = Get-Credential 
	PS> Invoke-RemoteCommand -commandline "dir c:\" -ComputerName "targetComputer" -Credential (Get-Credential) -CmdCredential $credExec
			

	Description
	-----------
	Connect to targetComputer using prompted credential. The "dir c:\" will be executed using credential from $credExec variable.    
		
.EXAMPLE
	PS> Invoke-RemoteCommand -commandline "`"%programfiles%\common files\microsoft shared\web server extensions\12\bin\stsadm.exe`"" -ComputerName "targetComputer" -Credential (Get-Credential)


	Description
	-----------
	Execute fullpath of commandline. Don't forget to put the commandline inside double quote. The commandline will be executed using prompted credential.
    
            
.LINK
    Author blog  : IdeasForFree  (http://blog.libinuko.com)
.LINK
    Author email : cakriwut@gmail.com
#>
   param(             
       [Parameter(Mandatory=$true, Position=0)]
       [System.String]            
       $CommandLine ,
       
       [Parameter(Mandatory=$true,Position=1)]
       [System.Management.Automation.PSCredential]        
       $Credential  ,
         
       [String] 
       $ComputerName = "."    ,
       
       [System.Management.Automation.PSCredential]        
       $CmdCredential     
        
   ) 

    if(!$CmdCredential)
    {
          $CmdCredential = $Credential
    }
    
    Invoke-Command -ComputerName $ComputerName -Credential $Credential `
        -script $function:InvokeScheduleTasks `
        -Args $commandline,$CmdCredential.UserName,$CmdCredential.GetNetworkCredential().Password    
         
}